package com.xy.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tencentcloudapi.faceid.v20180301.models.ImageRecognitionResponse;
import com.tencentcloudapi.iai.v20200303.models.DetectFaceResponse;
import com.xy.constants.RedisConstant;
import com.xy.dto.RealNameDTO;
import com.xy.entity.*;
import com.xy.service.*;
import com.xy.tx.TxCommon;
import com.xy.utils.CommonUtil;
import com.xy.utils.IdCarUtils;
import com.xy.vo.RealNameSortVO;
import com.xy.vo.RealNameTimeVO;
import com.xy.vo.RealNameVO;
import io.swagger.models.auth.In;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.excel.support.ExcelException;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class RealAuthServiceImpl implements RealAuthService {
	private final IViewerService viewerService;
	private final IViewerSortService viewerSortService;
	private final BladeRedis bladeRedis;
	private final ITimeStageService timeStageService;
	private final IExhibitionConfigService exhibitionConfigService;
	private final IExhibitionService exhibitionService;
	private final IAuthRecordService recordService;
	@Override
	public RealNameVO getRleaName(RealNameDTO realNameDTO) {

		ExhibitionEntity exhibitionEntity = exhibitionService.getById(Func.toLong(realNameDTO.getExhibitionId()));
		if(Func.isEmpty(exhibitionEntity) || exhibitionEntity.getCloseStatus().equals(1)){
			throw new ServiceException("展会不存在、或者已关闭");
		}

		List<ViewerEntity> viewerList = viewerService.list(Wrappers.<ViewerEntity>query().lambda().eq(ViewerEntity::getIdCard, realNameDTO.getIdCard()).eq(ViewerEntity::getExhibitionId,realNameDTO.getExhibitionId()));
		ExhibitionConfigEntity exhibitionConfig = exhibitionConfigService.getOne(Wrappers.<ExhibitionConfigEntity>query().lambda().eq(ExhibitionConfigEntity::getExhibitionId, realNameDTO.getExhibitionId()));
		if(Func.isEmpty(viewerList)  ){
			if("1".equals(exhibitionConfig.getOauthReg())){
				throw new ServiceException("用户不存在");
			}
			//开启注册
			long toLongExhibitionId = Func.toLong(realNameDTO.getExhibitionId());
//			Long viewerSortId = getViewerSort(exhibitionConfig.getTypeName(), toLongExhibitionId);
			ViewerEntity viewerEntity = BeanUtil.newInstance(ViewerEntity.class);
			viewerEntity.setViewerTypeId(Func.toLong(exhibitionConfig.getTypeName()));
			viewerEntity.setExhibitionId(toLongExhibitionId);
			viewerEntity.setName(realNameDTO.getName());
			viewerEntity.setIdCard(realNameDTO.getIdCard());
			viewerEntity.setTwoCode(CommonUtil.deviceNo());
			viewerEntity.setViewerStatus(0);
			viewerService.save(viewerEntity);
			viewerList.add(viewerEntity);
		}
		// 黑名单 展会
		String keyExhibitionId = RedisConstant.LIMITED_ACCESS.concat(realNameDTO.getExhibitionId()).concat(realNameDTO.getIdCard());
		Object o1 = bladeRedis.get(keyExhibitionId);
		if (Func.isNotEmpty(o1)) {
			throw new ServiceException("用户信息受限");
		}
		List<RealNameSortVO> nameSortList = new ArrayList<>();
		RealNameVO realName = BeanUtil.instantiateClass(RealNameVO.class);
		RealNameSortVO realNameSort = BeanUtil.newInstance(RealNameSortVO.class);
		realName.setOauthMode(exhibitionConfig.getOauthMode());
		realNameSort.setEntranceStatus(0);
		viewerList.forEach(o->{
			ViewerSortEntity viewerSort = viewerSortService.getById(o.getViewerTypeId());
			realNameSort.setId(Func.toStr(o.getId()));
			realNameSort.setTypeName(viewerSort.getSortName());
			realNameSort.setTwoCode(o.getTwoCode());
			List<RealNameTimeVO> timeVOList = new ArrayList<>();
			List<TimeStageEntity> stageEntityList = timeStageService.list(Wrappers.<TimeStageEntity>query().lambda().eq(TimeStageEntity::getViewerId, viewerSort.getId()));
			boolean allMatch = stageEntityList.stream().anyMatch(t -> {
				RealNameTimeVO realNameTime= BeanUtil.newInstance(RealNameTimeVO.class);
				realNameTime.setStartTime(t.getStartTime());
				realNameTime.setEndTime(t.getEndTime());
				timeVOList.add(realNameTime);
				//入场时间
				if (DateUtil.belongCalendar(new Date(), DateUtil.minusDays(t.getStartTime(), 0), t.getEndTime())) {
					return true;
				}
				return false;
			});

			if ((Func.isNotEmpty(stageEntityList) && !allMatch )|| o.getViewerStatus().equals(1)) {
				realNameSort.setEntranceStatus(1);
			}
			realNameSort.setTimeList(timeVOList);
			nameSortList.add(realNameSort);
			realName.setName(o.getName());
			realName.setHeadUrl(0==o.getAuthResulet()?o.getHeadUrl():"" );
			realName.setRealNameStatus(Func.toStr(o.getAuthResulet()));
			realName.setIdCard(o.getIdCard());
		});
		// 返回对象集合先以类属性一升序，再以属性二升序
		List<RealNameSortVO> sortVOList = nameSortList.stream().sorted(Comparator.comparing(RealNameSortVO::getEntranceStatus)).collect(Collectors.toList());
		realName.setRealNameSortList(sortVOList);
		return  realName;
	}

	@Override
	public Boolean chekFace(String headUrl) {
		DetectFaceResponse faceResponse = TxCommon.detectFace(headUrl);
		if(null == faceResponse){
			throw new ServiceException("请上传正确的头像");
		}
		String toJsonString = DetectFaceResponse.toJsonString(faceResponse);
		log.info("人脸检测返回值{}",toJsonString);
		JSONObject parseObject = JSONObject.parseObject(toJsonString);

		JSONArray faceInfos = parseObject.getJSONArray("FaceInfos");
		for(int i = 0 ;i<faceInfos.size();i++){
			JSONObject jsonObject = faceInfos.getJSONObject(i);
			JSONObject faceQualityInfo = jsonObject.getJSONObject("FaceQualityInfo");
			Float score = faceQualityInfo.getFloat("Score");
			if(score<70){
				throw new ServiceException("头像模糊、请重新上传");
			}
		}

		return true;
	}

	@Override
	public Boolean rleaNameAuth(RealNameDTO realNameDTO) {

		if(Func.isEmpty(realNameDTO.getName()) ){
			throw new ServiceException("请填写姓名");
		}
		if(Func.isEmpty(realNameDTO.getIdCard())){
			throw new ServiceException("请填写身份证号");
		}
		//三要素
		AuthRecordEntity authRecord = BeanUtil.newInstance(AuthRecordEntity.class);
		if(realNameDTO.getOauthMode().equals(1)){
			if(Func.isEmpty(realNameDTO.getHeadUrl())){
				throw new ServiceException("请上传头像");
			}
			IdCarUtils.Res res = IdCarUtils.faceIdCard(realNameDTO.getName(), realNameDTO.getIdCard().toUpperCase(), realNameDTO.getHeadUrl());

			if(res.getCode() != 200){
				addAuthRecord(authRecord,realNameDTO.getOauthMode(), realNameDTO, res);
				throw new ServiceException("认证失败");
			}
			if (res.getData().getIncorrect()!=100 || res.getData().getScore()<0.45) {
				addAuthRecord(authRecord,realNameDTO.getOauthMode(), realNameDTO, res);
				throw new ServiceException("认证失败、请检查身份信息以及头像");
			}
			authRecord.setAuthResulet(0);
			addAuthRecord(authRecord,realNameDTO.getOauthMode(), realNameDTO, res);
		}else {
			//二要素
			IdCarUtils.Res res = IdCarUtils.idCarVerify(realNameDTO.getName(), realNameDTO.getIdCard().toUpperCase());

			if (res.getCode() != 0) {
				addAuthRecord(authRecord,realNameDTO.getOauthMode(), realNameDTO, res);
				throw new ExcelException(res.getMessage());
			}
			IdCarUtils.CarInfo result = res.getResult();
			if (!Func.equals(result.getRes(), "1")) {
				addAuthRecord(authRecord,realNameDTO.getOauthMode(), realNameDTO, res);
				throw new ExcelException("身份证号与姓名不一致");
			}
			authRecord.setAuthResulet(0);
			addAuthRecord(authRecord,realNameDTO.getOauthMode(), realNameDTO, res);
		}


		List<ViewerEntity> viewerList = viewerService.list(Wrappers.<ViewerEntity>query().lambda().eq(ViewerEntity::getIdCard, realNameDTO.getIdCard()).eq(ViewerEntity::getExhibitionId,realNameDTO.getExhibitionId()));
		viewerList.forEach(o->{
			o.setHeadUrl(realNameDTO.getHeadUrl());
			o.setName(realNameDTO.getName());
			o.setAuthResulet(0);
		});
		if(Func.isNotEmpty(viewerList)){
			viewerService.updateBatchById(viewerList);
		}
		return true;
	}
	private Long  getViewerSort(String viewerTypeName,Long  exhibitionId){
		String key = RedisConstant.TYPE_ID_EX_TYPE_NAME.concat(Func.toStr(exhibitionId)).concat(viewerTypeName);
		ViewerSortEntity viewerSort = bladeRedis.get(key);
		if(Func.isNotEmpty(viewerSort)){
			return  viewerSort.getId();
		}
		 viewerSort = BeanUtil.newInstance(ViewerSortEntity.class);
		viewerSort.setSortName(viewerTypeName);
		viewerSort.setExhibitionId(exhibitionId);
		viewerSortService.save(viewerSort);
		bladeRedis.set(key,viewerSort.getId());
		return viewerSort.getId();
	}

	/**
	 * 认证记录
	 */
	private void addAuthRecord(AuthRecordEntity authRecord,Integer authType, RealNameDTO realNameDTO, IdCarUtils.Res res){
		authRecord.setAuthType(Func.toStr(authType));
		authRecord.setAuthInfo(Func.toStr(res));
		authRecord.setAuthHead(realNameDTO.getHeadUrl());
		authRecord.setAuthName(realNameDTO.getName());
		authRecord.setAuthIdCard(realNameDTO.getIdCard());
		authRecord.setExhibitionId(Func.toLong(realNameDTO.getExhibitionId()));
		recordService.save(authRecord);
	}

}
